#ifndef NETWORK_H
#define NETWORK_H

#include <fstream>
#include <string>
#include <vector>
#include <map>

  // Data for forwards backwards-star
  // point: second index 0 = regular point, 1 = rpoint
  // Node coordinates: Not stored atm.
  // Maps - maps a nodeid (nodenr) or linkid (linknr) to the node/link  number.
  // Vectors - maps a nodenr or linkr to nodeid resp. linkid.
  /* linktable: second index maps to:
     NETWORK_LINKTABLE_TAIL  = tail node
     NETWORK_LINKTABLE_HEAD  = head node
     NETWORK_LINKTABLE_TRACE = trace
  
     Capacitytable: second index maps to:
     NETWORK_CAPTABLE_COST - cost per unit flow
     NETWORK_CAPTABLE_CAP - capacity
     addiitonal numbers installable capacity in pairs
     2 = installable capacity
     3 = cost for installation
     with possibly more pairs
  
     Demand matrix - demand from node i to node j at index 
     demands[i,j] - demand from i to j.
   */


class network { 
  // Class scope constants
 public:
  static const int SUCCESS, FILE_NOT_VALID, FILE_NOT_OPEN, PARSE_ERROR; // Return values.
  static const int POINT_POINT, POINT_RPOINT, LINKTABLE_TAIL, LINKTABLE_HEAD, LINKTABLE_TRACE, CAPTABLE_COST, CAPTABLE_CAP, CAPTABLE_INST1, CAPTABLE_PRICE1; // Indices
  static const int DOES_NOT_EXIST, NOT_DEFINED;

 private:
  // ID<->number data.
  std::map<std::string, int> nodenr;
  std::map<std::string, int> linknr;
  std::vector<std::string> nodeid;
  std::vector<std::string> linkid;
  std::vector< std::pair<double, double> > nodecoordinates;

  // Forwards-backwards star data.
  std::vector< std::vector<int> > point;
  std::vector< std::vector <int> > linktable;
  std::vector< std::vector <double> > capacitytable;
  std::vector< std::vector <double> > demands;

  // Help functions for read_network_file
  bool readline(std::ifstream &input, std::string &read_to);
  int readnodes(std::ifstream &netfile);
  int readlinks(std::ifstream &netfile);
  int readdemands(std::ifstream &netfile);
  void fillintrace();
  void makepointtable();

  // Help function for sorttable()
  void interchange_links(int i, int j);

 public:
  // Constructors
  network();
  network(std::string path);

  // Member functions

  // FILE ACCESS MEMBER FUNCTIONS
  int read_network_file(std::ifstream &netfile);
  int read_network_file(std::string path);
  int read_solution_file(std::ifstream &netfile);
  int read_solution_file(std::string path);


  // SORTING MEMBER FUNCTIONS
  bool linktablesorted() const; // True if linktablerow is sorted, false otherwise.
  void sortlinktable(); // Sort the link- and capacitytable.
  void make_bidirected(); // Makes an undirected graph to a bidirected graph by adding reverse links (and sorting them).


  // DATA ACCESS MEMBER FUNCTIONS
  unsigned int linktablerows() const; // Number of rows in linktable.
  unsigned int nodes() const; // Number of nodes .
  unsigned int nonzerodemands() const;  // Total number of demands.
  unsigned int nonzerodemands(unsigned int to) const; // Number of demands to to.
  double demand(unsigned int from, unsigned int to) const;// Demand from from to to.
  double demand(unsigned int to) const; // Total demand to to.
  bool demand_to_node(unsigned int to) const;
  unsigned int nodes_with_nonzerodemands() const;
  int nonzero_demand_node_index(unsigned int nodenr) const;
  int nonzero_demand_node_from_index(unsigned int index) const;
  int get_demand_index(unsigned int to, unsigned int from) const;
  double get_demand_from_index(unsigned int index) const;
  std::vector<int> get_fromto_from_index(unsigned int index) const;

  int get_link_nr(unsigned int from, unsigned int to) const; // Returns the linknr for the link from from to to. -1 if no such link exists;
  int get_reverse_link_nr(int linknr) const;
  std::pair<double, double> get_node_coordinates(unsigned int nodenr);

  std::vector<int> linktablerow(unsigned int rownumber); // Returns row rownumber of linktable.
  std::vector<double> capacitytablerow(unsigned int rownumber);  // Returns row rownumber of capacitytable
  std::vector<int> pointrow(unsigned int rownumber); // Returns row rownumber of point.

  // const_iterators for reading the tables directly
  std::vector< std::vector<int> >::const_iterator point_begin();
  std::vector< std::vector<int> >::const_iterator point_end();
  std::vector< std::vector<int> >::const_iterator linktable_begin();
  std::vector< std::vector<int> >::const_iterator linktable_end();
  std::vector< std::vector<double> >::const_iterator capacitytable_begin();
  std::vector< std::vector<double> >::const_iterator capacitytable_end();

  // MISC DATA ASSIGNMENT MEMBER FUNCTIONS
  void assign_random_link_costs(int min, int max); // Put random link costs for usage on every link without a cost.
  int assign_capacities(std::vector<double> caps);
};

#endif
